#include "VideoPage.h"
#include "NavigationController.h"

#include <QVBoxLayout>
#include <QFileDialog>
#include <QStandardPaths>
#include <QSpacerItem>
#include <QIcon>
#include <QMediaDevices>
#include <QAudioDevice>

VideoPage::VideoPage() : MyPage()
{
	qDebug() << "VideoPage init";

	audioOutput = new QAudioOutput(this);
	player = new QMediaPlayer();

	createAction();
	createMenu();
	createToolBar();

	audioOutputComboBox = new QComboBox();
	audioOutputComboBox->addItem(QStringLiteral("Default"), QVariant::fromValue(QAudioDevice()));
	for (auto &deviceInfo : QMediaDevices::audioOutputs())
		audioOutputComboBox->addItem(deviceInfo.description(), QVariant::fromValue(deviceInfo));

	setupUI();

	connect(audioOutputComboBox, QOverload<int>::of(&QComboBox::activated), this, &VideoPage::audioOutputChanged);
	connect(positionSlider, &QSlider::sliderMoved, this, &VideoPage::positionSliderMoved);
	connect(positionSlider, &QSlider::rangeChanged, this, &VideoPage::positionSliderRangeChanged);
	connect(positionSlider, &QSlider::valueChanged, this, &VideoPage::positionSliderValueChanged);
	connect(volumeSlider, &QSlider::sliderMoved, this, &VideoPage::volumeSliderMoved);
	connect(volumeSlider, &QSlider::valueChanged, this, &VideoPage::volumeSliderValueChanged);
	connect(player, &QMediaPlayer::positionChanged, this, &VideoPage::playerPositionChanged);
	connect(player, &QMediaPlayer::durationChanged, this, &VideoPage::playerDurationChanged);
	connect(player, &QMediaPlayer::sourceChanged, this, &VideoPage::playerSourceChanged);
	connect(player, &QMediaPlayer::playbackRateChanged, this, &VideoPage::playerRateChanged);

	connect(&playList, &VideoPlayList::playListChanged, this, &VideoPage::playListChanged);
	connect(&playList, &VideoPlayList::currentIndexChanged, this, &VideoPage::currentIndexChanged);
	connect(playListWidget, &QListWidget::itemDoubleClicked, this, &VideoPage::playListDoubleClicked);

	volumeSlider->setValue(50);
	audioOutput->setVolume(0.5);
	player->setVideoOutput(videoWidget);
	player->setAudioOutput(audioOutput);

	pausePlayer();
}

QWidget* VideoPage::getWidget()
{
	return this->widget;
}

void VideoPage::setupUI()
{
    QLabel *tmpLabel = new QLabel();
    QFont font = tmpLabel->font();
    font.setPixelSize(16);

	widget = new QWidget();
	vLayout_1 = new QVBoxLayout(widget);

	hLayout_1 = new QHBoxLayout();
    QLabel *tmpLabel0 = new QLabel("音频输出:");
    tmpLabel0->setMinimumHeight(30);
    tmpLabel0->setMaximumHeight(30);
    tmpLabel0->setFont(font);
	hLayout_1->addWidget(headBar);
    hLayout_1->addWidget(tmpLabel0);
    hLayout_1->addWidget(audioOutputComboBox);
	hLayout_1->addSpacerItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));

	hLayout_2 = new QHBoxLayout();
	vLayout_2 = new QVBoxLayout();
	videoNameLabel = new QLabel("");
	videoNameLabel->setMinimumHeight(30);
	videoNameLabel->setMaximumHeight(30);
	videoNameLabel->setAlignment(Qt::AlignCenter);
    font.setPixelSize(20);
	videoNameLabel->setFont(font);
	videoWidget = new MyVideoWidget(this, playMenu, widget);

	hLayout_3 = new QHBoxLayout();
	positionSlider = new QSlider(Qt::Orientation::Horizontal);
	positionSlider->setMinimumHeight(30);
	positionSlider->setMaximumHeight(30);
	volumeSlider = new QSlider(Qt::Orientation::Horizontal);
	volumeSlider->setMinimumHeight(30);
	volumeSlider->setMaximumHeight(30);
	volumeSlider->setMinimumWidth(100);
	volumeSlider->setMaximumWidth(100);
	volumeSlider->setMinimum(0);
	volumeSlider->setMaximum(100);
	openVolumeAction->setDisabled(true);
	volumeLabel = new QLabel("");
	volumeLabel->setMinimumHeight(30);
	volumeLabel->setMaximumHeight(30);
	volumeLabel->setMinimumWidth(25);
	volumeLabel->setMaximumWidth(25);
	font.setPixelSize(16);
	volumeLabel->setFont(font);
	hLayout_3->addWidget(positionSlider, 5);
	hLayout_3->addWidget(volumeControlBar);
	hLayout_3->addWidget(volumeSlider, 1);
	hLayout_3->addWidget(volumeLabel);

	hLayout_4 = new QHBoxLayout();
	QLabel *tmpLabel1 = new QLabel("倍速:");
	tmpLabel1->setMinimumHeight(30);
	tmpLabel1->setMaximumHeight(30);
	tmpLabel1->setFont(font);
	playSpeedLabel = new QLabel("1.00");
	playSpeedLabel->setMinimumHeight(30);
	playSpeedLabel->setMaximumHeight(30);
	playSpeedLabel->setFont(font);
	currentPositionLabel = new QLabel("0:00:00");
	currentPositionLabel->setMinimumHeight(30);
	currentPositionLabel->setMaximumHeight(30);
	currentPositionLabel->setFont(font);
	totalPositionLabel = new QLabel("0:00:00");
	totalPositionLabel->setMinimumHeight(30);
	totalPositionLabel->setMaximumHeight(30);
	totalPositionLabel->setFont(font);
	QLabel *tmpLabel2 = new QLabel("/");
	tmpLabel2->setMinimumHeight(30);
	tmpLabel2->setMaximumHeight(30);
	tmpLabel2->setFont(font);
	hLayout_4->addWidget(playControlBar);
	hLayout_4->addSpacerItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
	hLayout_4->addSpacing(30);
	hLayout_4->addWidget(tmpLabel1);
	hLayout_4->addWidget(playSpeedLabel);
	hLayout_4->addSpacing(30);
	hLayout_4->addWidget(currentPositionLabel);
	hLayout_4->addWidget(tmpLabel2);
	hLayout_4->addWidget(totalPositionLabel);

	vLayout_2->addWidget(videoNameLabel);
	vLayout_2->addWidget(videoWidget);
	vLayout_2->addLayout(hLayout_3);
	vLayout_2->addLayout(hLayout_4);

	playListBox = new QWidget(widget);
	vLayout_3 = new QVBoxLayout(playListBox);
	QLabel *tmpLabel3 = new QLabel("播放列表");
	tmpLabel3->setMinimumHeight(30);
	tmpLabel3->setMaximumHeight(30);
	tmpLabel3->setFont(font);
	tmpLabel3->setAlignment(Qt::AlignCenter);
	playListWidget = new QListWidget();
    playListWidget->setMinimumWidth(150);
	playListWidget->setMaximumWidth(350);
	playListWidget->setFont(font);
	vLayout_3->addWidget(tmpLabel3);
	vLayout_3->addWidget(playListWidget);

	hLayout_2->addLayout(vLayout_2, 3);
	hLayout_2->addWidget(playListBox, 1);

	vLayout_1->addLayout(hLayout_1);
	vLayout_1->addLayout(hLayout_2);
}

void VideoPage::createAction()
{
	goHomeAction  = new QAction("返回", this->widget);
	goHomeAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::GoHome));
	connect(goHomeAction, &QAction::triggered, this, &VideoPage::goHome);

	openFileAction = new QAction("打开", this->widget);
	openFileAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen));
	openFileAction->setShortcut(QKeySequence("Ctrl+O"));
	connect(openFileAction, &QAction::triggered, this, &VideoPage::openFile);

	pausePlayAction = new QAction("暂停", this->widget);
	pausePlayAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaPlaybackPause));
	connect(pausePlayAction, &QAction::triggered, this, &VideoPage::pausePlayer);

	startPlayAction = new QAction("播放", this->widget);
	startPlayAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaPlaybackStart));
	connect(startPlayAction, &QAction::triggered, this, &VideoPage::startPlayer);

	stopPlayAction = new QAction("停止", this->widget);
	stopPlayAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaPlaybackStop));
	connect(stopPlayAction, &QAction::triggered, this, &VideoPage::stopPlayer);

	enableFullScreenAction = new QAction("全屏", this->widget);
	enableFullScreenAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ViewFullscreen));
	connect(enableFullScreenAction, &QAction::triggered, this, &VideoPage::enablePlayerFullScreen);

	disableFullScreenAction = new QAction("退出全屏", this->widget);
	disableFullScreenAction->setShortcut(QKeySequence("Esc"));
	connect(disableFullScreenAction, &QAction::triggered, this, &VideoPage::disablePlayerFullScreen);

	skipForwardAction = new QAction("快进", this->widget);
	skipForwardAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ViewRefresh));
	skipForwardAction->setShortcut(QKeySequence("Right"));
	connect(skipForwardAction, &QAction::triggered, this, &VideoPage::skipForward);

	skipBackwardAction = new QAction("快退", this->widget);
	skipBackwardAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ViewRestore));
	skipBackwardAction->setShortcut(QKeySequence("Left"));
	connect(skipBackwardAction, &QAction::triggered, this, &VideoPage::skipBackward);

	playSpeedUpAction = new QAction("加速", this->widget);
	playSpeedUpAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaSeekForward));
	playSpeedUpAction->setShortcut(QKeySequence("D"));
	connect(playSpeedUpAction, &QAction::triggered, this, &VideoPage::playSpeedUp);

	playSpeedDownAction = new QAction("减速", this->widget);
	playSpeedDownAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaSeekBackward));
	playSpeedDownAction->setShortcut(QKeySequence("A"));
	connect(playSpeedDownAction, &QAction::triggered, this, &VideoPage::playSpeedDown);

	closeVolumeAction = new QAction("静音", this->widget);
	closeVolumeAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::AudioVolumeMuted));
	closeVolumeAction->setShortcut(QKeySequence("M"));
	connect(closeVolumeAction, &QAction::triggered, this, &VideoPage::closeVolume);

	openVolumeAction = new QAction("取消静音", this->widget);
	openVolumeAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::AudioVolumeHigh));
	openVolumeAction->setShortcut(QKeySequence("N"));
	connect(openVolumeAction, &QAction::triggered, this, &VideoPage::openVolume);

	switchPlayListAction = new QAction("显示/隐藏列表", this->widget);
	switchPlayListAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::EditPaste));
	switchPlayListAction->setShortcut(QKeySequence("L"));
	connect(switchPlayListAction, &QAction::triggered, this, &VideoPage::switchPlayList);

	playNextAction = new QAction("下一个", this->widget);
	playNextAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaSkipForward));
	playNextAction->setShortcut(QKeySequence("S"));
	connect(playNextAction, &QAction::triggered, this, &VideoPage::playNext);

	playPreviousAction = new QAction("上一个", this->widget);
	playPreviousAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaSkipBackward));
	playPreviousAction->setShortcut(QKeySequence("W"));
	connect(playPreviousAction, &QAction::triggered, this, &VideoPage::playPrevious);

	togglePlayAction = new QAction("切换播放", this->widget);
	togglePlayAction->setShortcut(QKeySequence("Space"));
	connect(togglePlayAction, &QAction::triggered, this, &VideoPage::togglePlay);
}

void VideoPage::createMenu()
{
	playMenu = new QMenu();
	playMenu->addAction(openFileAction);
	playMenu->addSeparator();
	playMenu->addAction(togglePlayAction);
	playMenu->addAction(pausePlayAction);
	playMenu->addAction(startPlayAction);
	playMenu->addAction(stopPlayAction);
	playMenu->addSeparator();
	playMenu->addAction(skipForwardAction);
	playMenu->addAction(skipBackwardAction);
	playMenu->addSeparator();
	playMenu->addAction(enableFullScreenAction);
	playMenu->addAction(disableFullScreenAction);
	playMenu->addSeparator();
	playMenu->addAction(playSpeedUpAction);
	playMenu->addAction(playSpeedDownAction);
	playMenu->addSeparator();
	playMenu->addAction(closeVolumeAction);
	playMenu->addAction(openVolumeAction);
	playMenu->addSeparator();
	playMenu->addAction(goHomeAction);
	playMenu->addSeparator();
	playMenu->addAction(switchPlayListAction);
	playMenu->addAction(playNextAction);
	playMenu->addAction(playPreviousAction);
}

void VideoPage::createToolBar()
{
	playControlBar = new QToolBar();
	playControlBar->setMinimumHeight(30);
	playControlBar->setMaximumHeight(30);
	playControlBar->setMinimumWidth(250);
	playControlBar->addAction(togglePlayAction);
	playControlBar->addAction(stopPlayAction);
	playControlBar->addAction(skipBackwardAction);
	playControlBar->addAction(skipForwardAction);
	playControlBar->addAction(playSpeedDownAction);
	playControlBar->addAction(playSpeedUpAction);

	volumeControlBar = new QToolBar();
	volumeControlBar->setMinimumHeight(30);
	volumeControlBar->setMaximumHeight(30);
	volumeControlBar->addAction(closeVolumeAction);
	volumeControlBar->addAction(openVolumeAction);

	headBar = new QToolBar();
	headBar->addAction(goHomeAction);
	headBar->addAction(openFileAction);
	headBar->addAction(enableFullScreenAction);
	headBar->addAction(switchPlayListAction);
	headBar->addAction(playPreviousAction);
	headBar->addAction(playNextAction);
}

void VideoPage::goHome()
{
	pausePlayer();
	MyNavigationController::instance().backToMainPage();
}

void VideoPage::openFile()
{
	QFileDialog fileDialog(this->widget);
	QStringList filters;
	filters << "Video (*.mp4 *.avi *.wmv)"
			<< "Audio (*.mp3 *.wav *.aac)";
	fileDialog.setNameFilters(filters);
	fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
	fileDialog.setFileMode(QFileDialog::ExistingFiles);
	fileDialog.setWindowTitle(tr("Open Files"));
	fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath()));


	if (fileDialog.exec() == QDialog::Accepted)
	{
		playList.addToPlayList(fileDialog.selectedUrls());
	}
}

void VideoPage::pausePlayer()
{
	player->pause();
	startPlayAction->setEnabled(true);
	pausePlayAction->setDisabled(true);
	updateToggleIcon();
}

void VideoPage::startPlayer()
{
	player->play();
	pausePlayAction->setEnabled(true);
	startPlayAction->setDisabled(true);
	updateToggleIcon();
}

void VideoPage::stopPlayer()
{
	player->stop();
	startPlayAction->setEnabled(true);
	pausePlayAction->setDisabled(true);
}

void VideoPage::enablePlayerFullScreen()
{
	videoWidget->setFullScreen(true);
}

void VideoPage::disablePlayerFullScreen()
{
	videoWidget->setFullScreen(false);
}

void VideoPage::skipForward()
{
	qint64 curPos = player->position();
	player->setPosition(curPos + 10000);
}

void VideoPage::skipBackward()
{
	qint64 curPos = player->position();
	player->setPosition(curPos - 10000);
}

void VideoPage::playSpeedUp()
{
	player->setPlaybackRate(player->playbackRate() * 1.25);
}

void VideoPage::playSpeedDown()
{
	player->setPlaybackRate(player->playbackRate() / 1.25);
}

void VideoPage::closeVolume()
{
	previousVolume = audioOutput->volume();
	audioOutput->setVolume(0);
	volumeSlider->setSliderPosition(0);
	volumeSlider->setDisabled(true);
	openVolumeAction->setEnabled(true);
	closeVolumeAction->setDisabled(true);
}

void VideoPage::openVolume()
{
	audioOutput->setVolume(previousVolume);
	volumeSlider->setEnabled(true);
	volumeSlider->setSliderPosition(int(previousVolume * 100));
	closeVolumeAction->setEnabled(true);
	openVolumeAction->setDisabled(true);
}

void VideoPage::setPlaySource(QUrl url)
{
	player->setSource(url);
	pausePlayer();
}

void VideoPage::positionSliderMoved(int value)
{
	player->setPosition(value);
}

void VideoPage::positionSliderValueChanged(int value)
{
	int secs = value / 1000;
	int mins = secs / 60; secs %= 60;
	int hours = mins / 60; mins %= 60;
	currentPositionLabel->setText(QString::asprintf("%d:%02d:%02d", hours, mins, secs));
}

void VideoPage::positionSliderRangeChanged(int min, int max)
{
	Q_UNUSED(min);
	int secs = max / 1000;
	int mins = secs / 60; secs %= 60;
	int hours = mins / 60; mins %= 60;
	totalPositionLabel->setText(QString::asprintf("%d:%02d:%02d", hours, mins, secs));
}

void VideoPage::playerPositionChanged(qint64 value)
{
	if(positionSlider->isSliderDown()) return;
	positionSlider->setSliderPosition(value);
}

void VideoPage::playerDurationChanged(qint64 value)
{
	positionSlider->setMaximum(value);
}

void VideoPage::volumeSliderMoved(int value)
{
	audioOutput->setVolume(value / 100.0);
}

void VideoPage::volumeSliderValueChanged(int value)
{
	volumeLabel->setText(QString::asprintf("%d", value));
}

void VideoPage::playerSourceChanged(QUrl url)
{
	videoNameLabel->setText(url.fileName());
}

void VideoPage::playerRateChanged(qreal rate)
{
	playSpeedLabel->setText(QString::asprintf("%.2lf", rate));
}

void VideoPage::audioOutputChanged(int indx)
{
	QAudioDevice device = audioOutputComboBox->itemData(indx).value<QAudioDevice>();
	audioOutput->setDevice(device);
}

void VideoPage::switchPlayList()
{
	if(playListBox->isVisible())
		playListBox->hide();
	else
	{
		disablePlayerFullScreen();
		playListBox->show();
	}
}

void VideoPage::playListChanged()
{
	playListWidget->clear();
	QList<QUrl> urls = playList.getList();
	int indx = 0;
	for(QUrl url : urls)
	{
		QListWidgetItem *item = new QListWidgetItem();
		item->setText(url.fileName());
		item->setData(Qt::UserRole, indx);
		playListWidget->addItem(item);
		indx++;
	}
}

void VideoPage::currentIndexChanged(int index)
{
	playListWidget->setCurrentRow(index);
	setPlaySource(playList.getCurrentUrl());
}

void VideoPage::playListDoubleClicked(QListWidgetItem *item)
{
	playList.setCurrentUrl(item->data(Qt::UserRole).toInt());
}

void VideoPage::playNext()
{
	playList.playNext();
}

void VideoPage::playPrevious()
{
	playList.playPrevious();
}

void VideoPage::togglePlay()
{
	if(player->isPlaying()) pausePlayer();
	else startPlayer();
}

void VideoPage::updateToggleIcon()
{
	if(player->isPlaying()) togglePlayAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaPlaybackPause));
	else togglePlayAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::MediaPlaybackStart));
}
